package controllers;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import models.*;
import play.mvc.Controller;

/**
 * 
 * @author Rana Ramez
 * 
 */
public class Report extends Controller {

	/**
	 * this method is the action method for producing the selection page
	 * 
	 * @param projectId
	 */
	public static void reportSelection(long projectId) {
		Security.checkAccess("View reports and statistics", projectId,
				Project.class.getName());
		Project project = Project.findById(projectId);
		if (project != null) {
			List<Component> components = new LinkedList<Component>();
			List<TaskType> taskTypes = TaskType.getAllTaskTypes();
			List<TaskStatus> taskStatuses = TaskStatus.getAllTaskStatuses();
			Set<EventType> eventTypes = new HashSet<EventType>();
			List<EventType> typesList = new LinkedList<EventType>();
			if (!project.components.isEmpty()) {
				components = project.components;
				for (int i = 0; i < components.size(); i++) {
					if (components.get(i).name.equals("Default component")) {
						components.remove(i);
						break;
					}
				}
			}
			if (!project.events.isEmpty()) {
				List<Event> events = project.events;
				for (int i = 0; i < events.size(); i++) {
					if (!events.get(i).type.type.equals("Default"))
						typesList.add(events.get(i).type);
				}
				eventTypes.addAll(typesList);
			}
			if (!project.taskTypes.isEmpty()) {
				List<TaskType> projectTypes = project.taskTypes;
				for (int i = 0; i < projectTypes.size(); i++) {
					taskTypes.add(projectTypes.get(i));
				}
			}
			if (!project.taskStatuses.isEmpty()) {
				List<TaskStatus> projectStatus = project.taskStatuses;
				for (int i = 0; i < projectStatus.size(); i++) {
					taskStatuses.add(projectStatus.get(i));
				}
			}
			render(components, taskStatuses, taskTypes, eventTypes, project);
		} else {
			forbidden();
		}
	}

	/*
	 * renders a list of notes associated with a certain project along with the
	 * project entity
	 */
	public static void viewRetroReport(long projectId) {
		Security.checkAccess("View the project backlog", projectId,
				Project.class.getName());
		boolean hasReviewNotes = false;
		Project project = Project.findById(projectId);
		List<Event> eventsList = project.events;
		List<Note> notesList = new LinkedList<Note>();
		List<User> userList = new LinkedList<User>();
		List<UserRoleProject> urpl = new LinkedList<UserRoleProject>();
		Event event = new Event();
		Event x = new Event();
		for (int i = 0; i < eventsList.size(); i++) {
			for (int j = 0; j < eventsList.get(i).notes.size(); j++) {
				EventType eventType = EventType.findById(eventsList.get(i).type
						.getEntityId());
				if (eventType.type.equalsIgnoreCase("Sprint Review")) {
					event = Event.find("name", eventsList.get(i).name).first();
					notesList.add(eventsList.get(i).notes.get(j));
					String firstName = eventsList.get(i).notes.get(j).user.firstName;
					User user = User.find("firstName", firstName).first();
					userList.add(user);
					urpl = UserRoleProject.find("project", project).fetch();
					x = event.sprint;

				} else {
					continue;
				}
			}
		}

		if (notesList.isEmpty())
			hasReviewNotes = false;
		else {
			hasReviewNotes = true;
		}
		render(project, urpl, notesList, hasReviewNotes, event, userList, x);
	}

	/**
	 * This methods gets the events related to a project according to specific
	 * condition
	 * 
	 * @author Rana Ramez
	 * @param eventTypes
	 * @param projectId
	 * @return
	 */
	public static List<Event> eventsModel(LinkedList<Long> eventTypes,
			long projectId) {
		List<Event> result = new LinkedList<Event>();
		Project project = Project.findById(projectId);
		if (!eventTypes.isEmpty()) {
			while (!eventTypes.isEmpty()) {
				EventType type = EventType.findById(eventTypes.removeFirst());
				List<Event> event = Event.find(
						"select e from Event e where e.type=? and e.project=?",
						type, project).fetch();
				if (!event.isEmpty()) {
					for (int i = 0; i < event.size(); i++) {
						if (!event.get(i).description.equals("default"))
							result.add(event.get(i));
					}
				}
			}
		} else {
			List<Event> event = Event.find(
					"select e from Event e where e.project=?", project).fetch();
			if (!event.isEmpty()) {
				for (int i = 0; i < event.size(); i++) {
					if (!event.get(i).description.equals("default"))
						result.add(event.get(i));
				}
			}
		}
		return result;
	}

	/**
	 * this method geta the components related to a project according to
	 * specific conditions
	 * 
	 * @param components
	 * @param projectId
	 * @return List<Component>
	 */
	public static List<Component> componentModel(LinkedList<Long> components,
			long projectId) {
		List<Component> result = new LinkedList<Component>();
		Project project = Project.findById(projectId);
		if (!components.isEmpty()) {
			while (!components.isEmpty()) {
				Component comp = Component.findById(components.removeFirst());
				if (!comp.name.equals("Default component"))
					result.add(comp);
			}
		} else {
			result = project.components;
			for (int i = 0; i < result.size(); i++) {
				if (result.get(i).name.equals("Default component"))
					result.remove(i);
			}
		}
		return result;
	}

	/**
	 * gets the number of tasks with specific status
	 * 
	 * @param tasks
	 * @param status
	 * @return
	 */
	public static int numOfTasksWithStatus(LinkedList<Task> tasks, String status) {
		int counter = 0;
		for (int i = 0; i < tasks.size(); i++) {
			if (tasks.get(i).status.status.equals(status))
				counter++;
		}
		return counter;
	}

	/**
	 * this method gets All tasks related to a project according to the choise
	 * of the user(specific conditions)
	 * 
	 * @param taskStatus
	 * @param taskTypes
	 * @param projectId
	 * @return List<Task>
	 */
	public static List<Task> taskModel(LinkedList<Long> taskStatuss,
			LinkedList<Long> taskTypess, long projectId,
			LinkedList<String> result) {
		List<Task> eventTasks = new LinkedList<Task>();
		LinkedList<Task> taskResult = new LinkedList<Task>();
		LinkedList<Long> taskStatus = new LinkedList<Long>();
		LinkedList<Long> taskTypes = new LinkedList<Long>();
		taskStatus.addAll(taskStatuss);
		taskTypes.addAll(taskTypess);
		Set<Task> te = new HashSet<Task>();
		LinkedList<Task> temp = new LinkedList<Task>();
		LinkedList<Task> finalTasks = new LinkedList<Task>();
		String message = "";
		Project project = Project.findById(projectId);
		if (!project.events.isEmpty()) {
			List<Event> events = project.events;
			for (int i = 0; i < events.size(); i++) {
				Event event = Event.findById(events.get(i).getEntityId());
				eventTasks = event.getEventTasks();
				for (int j = 0; j < eventTasks.size(); j++) {
					temp.addLast(eventTasks.get(j));
				}
			}
			te.addAll(temp);
			taskResult.addAll(te);
			if (!taskResult.isEmpty()) {
				message = "Total Number of Tasks in project: "
						+ taskResult.size();
			} else {
				message = "Total Number Of Tasks in Project: 0";
			}
			result.addLast(message);
			if (!taskStatus.isEmpty() || !taskTypes.isEmpty()) {

				if (!taskStatus.isEmpty()) {

					while (!taskStatus.isEmpty()) {
						TaskStatus st = TaskStatus.findById(taskStatus
								.removeFirst());
						message = "Number of Tasks With Status " + st.status
								+ " in project : "
								+ numOfTasksWithStatus(taskResult, st.status);
						result.addLast(message);
						for (int i = 0; i < taskResult.size(); i++) {
							if (taskResult.get(i).status == st) {
								finalTasks.addLast(taskResult.get(i));
							}
						}
					}
				}
				if (!taskTypes.isEmpty()) {
					while (!taskTypes.isEmpty()) {
						TaskType types = TaskType.findById(taskTypes
								.removeFirst());
						message = "Number of Tasks With Type " + types.type
								+ " in project : "
								+ numOfTasksWithType(taskResult, types.type);
						result.addLast(message);
						for (int i = 0; i < taskResult.size(); i++) {
							if (taskResult.get(i).type == types) {
								finalTasks.addLast(taskResult.get(i));
							}
						}
					}
				}
			} else {
				finalTasks = taskResult;
			}
		} else {
			message = "Total Number of Tasks in Project: " + 0;
			result.addLast(message);
			for (int i = 0; i < taskTypes.size(); i++) {
				TaskType t = TaskType.findById(taskTypes.get(i));
				message = "Number of Tasks with Type " + t.type
						+ " in project : 0";
				result.addLast(message);
			}
			for (int j = 0; j < taskStatus.size(); j++) {
				TaskStatus st = TaskStatus.findById(taskStatus.get(j));
				message = "Number of Tasks with status " + st.status
						+ " in project : 0";
				result.addLast(message);
			}
		}
		return finalTasks;
	}

	/**
	 * this method takes 2 lists of stories and returns the intersection between
	 * them
	 * 
	 * @param stories1
	 * @param stories2
	 * @return List<UserStory>
	 */
	public static List<UserStory> intersection(List<UserStory> stories1,
			List<UserStory> stories2) {
		List<UserStory> result = new LinkedList<UserStory>();
		for (UserStory story1 : stories1)
			if (stories2.contains(story1))
				result.add(story1);
		return result;
	}

	/**
	 * this method takes list of components and events with the story statuses
	 * to combine all together and gets the report for the userstory
	 * 
	 * @param comp
	 * @param event
	 * @param statuses
	 * @param result
	 * @return string with the resulted string
	 */
	public static String componentEventsReport(Component comp, Event event,
			List<String> statuses, LinkedList<String> result) {
		List<UserStory> eventStories = Events.getEventUserStories(event);
		List<UserStory> compAssignedStories = comp.userStoriesAssigned;
		List<UserStory> compDependantStories = comp.userStoriesDependant;
		List<UserStory> assignedStoriesInEvent = intersection(
				compAssignedStories, eventStories);
		List<UserStory> dependantStoriesInEvent = intersection(
				compDependantStories, eventStories);
		String res = "";
		res = "Component " + comp.name + " has "
				+ dependantStoriesInEvent.size()
				+ " dependant stories in event " + event.name;
		result.addLast(res);
		String m = comp.name + " In Event " + event.name;
		res = getStoriesReport(assignedStoriesInEvent, statuses, result, m);
		return res;
	}

	/**
	 * this method takes event and statuses to combine the event with the
	 * stories with the specific statuses to generate a report for the
	 * userstories
	 * 
	 * @param event
	 * @param statuses
	 * @param result
	 * @return
	 */
	public static String eventStoriesReport(Event event, List<String> statuses,
			LinkedList<String> result) {
		String res = "";
		List<UserStory> stories = Events.getEventUserStories(event);
		res = "Event " + event.name + " had " + stories.size() + " stories ";
		result.addLast(res);
		res += getStoriesReport(stories, statuses, result, event.name);

		return res;
	}

	/**
	 * this method takes component with story statuses and gets all the
	 * combination that can be diplayed in the userStory report
	 * 
	 * @param comp
	 * @param statuses
	 * @param result
	 * @return
	 */
	public static String componentStoriesReport(Component comp,
			List<String> statuses, LinkedList<String> result) {
		String res = "";
		List<UserStory> assignedStories = comp.userStoriesAssigned;
		res = "Component " + comp.name + " had " + assignedStories.size()
				+ " stories assigned :";
		result.addLast(res);
		res += getStoriesReport(assignedStories, statuses, result, comp.name);

		List<UserStory> dependantStories = comp.userStoriesDependant;
		res = "Component " + comp.name + " had " + dependantStories.size()
				+ " stories dependent : ";
		result.addLast(res);
		res += getStoriesReport(dependantStories, statuses, result, comp.name);

		return res;
	}

	/**
	 * this method is responsible for inserting the string with the data in the
	 * resulted list as to be displayed in the report
	 * 
	 * @param stories
	 * @param statusees
	 * @param result
	 * @param eventName
	 * @return
	 */
	public static String getStoriesReport(List<UserStory> stories,
			List<String> statusees, LinkedList<String> result, String eventName) {
		String res = "";
		List<String> statuses = statusees;
		for (String status : statuses) {
			res = "Number of Assigned stories with status " + status + " In  "
					+ eventName + " : "
					+ numOfStoriesWithStatus(stories, status);
			result.addLast(res);
		}
		return res;
	}

	/**
	 * this method gets number of statuses for a list of userStories
	 * 
	 * @param tasks
	 * @param Type
	 * @return
	 */
	public static int numOfStoriesWithStatus(List<UserStory> stories,
			String status) {
		int count = 0;
		for (UserStory story : stories)
			if (story.status.equals(status))
				count++;
		return count;
	}

	/**
	 * this method takes a status with the project and gets total number of
	 * userstory having this status in this project
	 * 
	 * @param status
	 * @param project
	 * @return
	 */
	public static int numOfStoryWithStatus(String status, Project project) {
		int count = 0;
		List<Event> events = project.events;
		for (int i = 0; i < events.size(); i++) {
			Event event = Event.findById(events.get(i).getEntityId());
			List<UserStory> stories = Events.getEventUserStories(event);
			for (UserStory story : stories)
				if (story.status.equals(status))
					count++;
		}

		return count;
	}

	/**
	 * this method is the parent method for generating the userStories report it
	 * calls its child methods to get all the data needed this is according to
	 * some condition is sent from the root method (Action method)
	 * 
	 * @param project
	 * @param comps
	 * @param events
	 * @param status
	 * @param result
	 * @return
	 */
	public static String report(Project project, List<Component> comps,
			List<Event> events, List<String> status, LinkedList<String> result) {
		String res = "";
		for (String statuses : status) {
			res = "Total Number of Stories with status " + statuses
					+ " in project is: "
					+ numOfStoryWithStatus(statuses, project);
			result.addLast(res);
		}
		if (!comps.isEmpty() && !events.isEmpty()) {
			for (Component comp : comps)
				for (Event event : events)
					res += componentEventsReport(comp, event, status, result);
		} else if (!comps.isEmpty() && events.isEmpty())
			for (Component comp : comps)
				res += componentStoriesReport(comp, status, result);
		else if (comps.isEmpty() && !events.isEmpty())
			for (Event event : events)
				res += eventStoriesReport(event, status, result);

		return res;
	}

	/**
	 * this is the action method for generating the report it takes all
	 * parameters from reportSelection page and collect the data needed by the
	 * user by calling the helper methods
	 * 
	 * @param projectId
	 * @param component
	 * @param taskTypes
	 * @param taskStatus
	 * @param storyStatus
	 * @param events
	 */
	public static void generateReport(long projectId, long[] component,
			long[] taskTypes, long[] taskStatus, long[] storyStatus,
			long[] events) {
		Security.checkAccess("View reports and statistics", projectId,
				Project.class.getName());
		LinkedList<String> result = new LinkedList<String>();
		LinkedList<String> storyResult = new LinkedList<String>();
		LinkedList<String> taskResult = new LinkedList<String>();
		LinkedList<String> componentsResult = new LinkedList<String>();
		LinkedList<String> eventResult = new LinkedList<String>();
		List<Component> compo = new LinkedList<Component>();
		Project project = Project.findById(projectId);
		List<Event> event = new LinkedList<Event>();
		List<Task> tasks = new LinkedList<Task>();
		LinkedList<Long> eventsId = new LinkedList<Long>();
		LinkedList<String> statuses = new LinkedList<String>();
		LinkedList<Long> comp = new LinkedList<Long>();
		LinkedList<Long> status = new LinkedList<Long>();
		LinkedList<Long> type = new LinkedList<Long>();
		String message = "";
		if (project != null) {
			if (component != null) {
				comp = getComponentsIds(component);
				compo = componentModel(comp, projectId);
			}
			if (taskStatus != null || taskTypes != null) {
				if (taskStatus == null) {
					type = getTaskTypes(taskTypes, projectId);
				} else if (taskTypes == null) {
					status = getTaskStatus(taskStatus, projectId);
				} else {
					type = getTaskTypes(taskTypes, projectId);
					status = getTaskStatus(taskStatus, projectId);
				}
				LinkedList<Long> temp = new LinkedList<Long>();
				temp.addAll(type);
				tasks = taskModel(status, temp, projectId, taskResult);

			}

			if (events != null) {
				eventsId = getEventsIds(events);
				event = eventsModel(eventsId, projectId);
			}
			if (storyStatus != null) {
				statuses = getStoryStatusIds(storyStatus);
			}

			if (!compo.isEmpty()) {
				for (int i = 0; i < compo.size(); i++) {
					message = "Team Members in Component " + compo.get(i).name
							+ " : " + compo.get(i).user_components.size();
					componentsResult.addLast(message);
				}
				if (!event.isEmpty()) {
					LinkedList<Event> eventTemp = new LinkedList<Event>();
					eventTemp.addAll(event);
					boolean m = eventReport(eventTemp, eventResult);

				}
				if (!tasks.isEmpty()) {
					boolean k = categorizeTasks(tasks, event, compo, taskResult);
				}
				if (!statuses.isEmpty()) {
					String storyMessage = report(project, compo, event,
							statuses, storyResult);
					// result.addLast(storyMessage);
				}

			} else if (!event.isEmpty()) {
				LinkedList<Event> eventTemp = new LinkedList<Event>();
				eventTemp.addAll(event);
				boolean m = eventReport(eventTemp, eventResult);
				if (!tasks.isEmpty()) {
					boolean k = categorizeTasks(tasks, event, compo, taskResult);
				}
				if (!statuses.isEmpty()) {
					String storyMessage = report(project, compo, event,
							statuses, storyResult);
					// result.addLast(storyMessage);
				}
			} else if (!tasks.isEmpty()) {
				boolean k = categorizeTasks(tasks, event, compo, taskResult);
				if (!statuses.isEmpty()) {
					String storyMessage = report(project, compo, event,
							statuses, storyResult);
					// result.addLast(storyMessage);
				}
			} else if (!statuses.isEmpty()) {
				String storyMessage = report(project, compo, event, statuses,
						storyResult);
			}
			boolean flag = true;
			if (taskResult.isEmpty() && storyResult.isEmpty()
					&& eventResult.isEmpty() && componentsResult.isEmpty()) {
				flag = false;
			}
			LinkedList<String> projectResult = new LinkedList<String>();
			int c = 0;
			if (!project.events.isEmpty()) {
				for (int i = 0; i < project.events.size(); i++) {
					if (!project.events.get(i).description.equals("default"))
						c++;
				}
			}
			String r = "Total Number of events in project is : " + c;
			projectResult.addLast(r);
			c = 0;
			if (!project.components.isEmpty()) {
				for (int i = 0; i < project.components.size(); i++) {
					if (!project.components.get(i).name
							.equals("Default component"))
						c++;
				}
			}
			r = "Total Number of Components in Project is : " + c;
			projectResult.addLast(r);
			r = "Total Number of user Roles in project : "
					+ project.user_project_roles.size();
			projectResult.addLast(r);
			r = "Total Number of application Role in Project: "
					+ project.appRoles.size();
			projectResult.addLast(r);
			render(project, projectResult, flag, taskResult, storyResult,
					eventResult, componentsResult);
		} else {
			forbidden();
		}
	}

	/**
	 * this method is responsible for converting an array of story ids a
	 * linkedlIST of story ids
	 * 
	 * @param storyStatus
	 * @return
	 */
	public static LinkedList<String> getStoryStatusIds(long[] storyStatus) {

		LinkedList<String> statuses = new LinkedList<String>();
		for (int i = 0; i < storyStatus.length; i++) {
			if (storyStatus[i] == 0) {
				if (!statuses.isEmpty()) {
					while (!statuses.isEmpty()) {
						statuses.removeFirst();
					}
				}
				statuses.addLast("NEW");
				statuses.addLast("IN PROGRESS");
				statuses.addLast("DONE");
				break;
			} else if (storyStatus[i] == 1) {
				statuses.addLast("NEW");
			} else if (storyStatus[i] == 2) {
				statuses.addLast("IN PROGRESS");
			} else if (storyStatus[i] == 3) {
				statuses.addLast("DONE");
			}
		}

		return statuses;
	}

	/**
	 * this method is responsible for getting the data needed for the choosen
	 * events this is called by generateReport action method according to
	 * specific conditions
	 * 
	 * @param eventTemp
	 * @param result
	 * @return
	 */
	public static boolean eventReport(LinkedList<Event> eventTemp,
			LinkedList<String> result) {
		int typeCount = 0;
		String message = "";
		while (!eventTemp.isEmpty()) {
			typeCount = 1;
			String ty = eventTemp.get(0).type.type;
			long typeId = (Long) eventTemp.remove(0).type.getEntityId();
			int listSize = eventTemp.size();
			while (listSize > 0) {
				EventType type = EventType.findById(typeId);
				if (type.type.equals(eventTemp.get(listSize - 1).type.type)) {
					eventTemp.remove(listSize - 1);
					typeCount++;
				}
				listSize--;
			}
			message = "Number of Events of Type " + ty + " in the project : "
					+ typeCount;
			result.addLast(message);
		}

		return true;
	}

	/**
	 * this method is responsible for converting an array of eventIds into a
	 * linkedlist of event ids
	 * 
	 * @param events
	 * @return
	 */
	public static LinkedList<Long> getEventsIds(long[] events) {
		LinkedList<Long> ids = new LinkedList<Long>();
		for (int i = 0; i < events.length; i++) {
			Event ev = Event.findById(events[i]);
			if (events[i] != 0) {
				if (!ev.description.equals("default")) {
					ids.add(events[i]);
				}

			} else {
				while (!ids.isEmpty()) {
					ids.removeFirst();
				}
				break;
			}
		}
		return ids;
	}

	/**
	 * this method gets total number of tasks with specific type
	 * 
	 * @param typesList
	 * @param type
	 * @return
	 */
	public static int numOfTasksWithType(LinkedList<Task> typesList, String type) {
		int counter = 0;
		for (int i = 0; i < typesList.size(); i++) {
			if (typesList.get(i).type.type.equals(type)) {
				counter++;
			}
		}
		return counter;
	}

	/**
	 * this method is the heart of the tasks report it takes the conditions and
	 * gather the data needed according to this conditions
	 * 
	 * @param tasks
	 * @param events
	 * @param components
	 * @param result
	 * @return
	 */
	public static boolean categorizeTasks(List<Task> tasks, List<Event> events,
			List<Component> components, LinkedList<String> result) {
		String message = "";
		LinkedList<TaskType> types = new LinkedList<TaskType>();
		Set<TaskType> typesList = new HashSet<TaskType>();
		for (int i = 0; i < tasks.size(); i++) {
			TaskType t = TaskType.findById(tasks.get(i).type.getEntityId());
			types.addLast(t);
		}
		typesList.addAll(types);
		// message="Total task types used in project : "+typesList.size();
		// result.addLast(message);
		if (!components.isEmpty() && events.isEmpty()) {

			boolean flag = getTasksComponentReport(components, typesList,
					tasks, result);

		} else if (!events.isEmpty() && components.isEmpty()) {
			boolean flag = getTasksEventsReport(typesList, events, tasks,
					result);

		} else if (!events.isEmpty() && !components.isEmpty()) {
			LinkedList<Task> t = new LinkedList<Task>();
			LinkedList<Task> temp = new LinkedList<Task>();
			t.addAll(tasks);
			temp.addAll(tasks);
			boolean f = getTasksEventsReport(typesList, events, t, result);
			boolean h = getTasksComponentReport(components, typesList, temp,
					result);
		}

		return true;
	}

	/**
	 * this method gets the data for the tasks related to specific components
	 * 
	 * @param components
	 * @param typesList
	 * @param task
	 * @param result
	 * @return
	 */
	public static boolean getTasksComponentReport(List<Component> components,
			Set<TaskType> typesList, List<Task> task, LinkedList<String> result) {
		int counter = 0;
		String message = "";
		LinkedList<Task> tasks = new LinkedList<Task>();
		tasks.addAll(task);
		LinkedList<Task> componentTasks = new LinkedList<Task>();
		for (int i = 0; i < components.size(); i++) {

			counter = 0;
			for (int j = 0; j < components.get(i).userStoriesAssigned.size(); j++) {
				for (int k = 0; k < components.get(i).userStoriesAssigned
						.get(j).tasks.size(); k++) {
					for (int l = 0; l < tasks.size(); l++) {
						if (components.get(i).userStoriesAssigned.get(j).tasks
								.get(k) == tasks.get(l)) {
							componentTasks.addLast(tasks.get(l));
							tasks.remove(l);
							l--;
							counter++;
						}
					}
				}
			}
			message = "Total Tasks in Component " + components.get(i).name
					+ " : " + counter;
			result.addLast(message);
			LinkedList<TaskType> tt = new LinkedList<TaskType>();
			tt.addAll(typesList);
			int typeCounter = 0;
			for (int m = 0; m < componentTasks.size(); m++) {
				typeCounter = 0;
				for (int n = 0; n < componentTasks.size(); n++) {
					if (tt.get(0) == componentTasks.get(n).type) {
						componentTasks.remove(n);
						n--;
						m--;
						typeCounter++;
					}
				}
				if (!tt.isEmpty() && !components.isEmpty()) {
					message = "Total Tasks of Type " + tt.get(0).type
							+ " In Component " + components.get(i).name + " : "
							+ typeCounter;
					tt.remove(0);
					result.addLast(message);
				}
			}
		}
		return true;
	}

	/**
	 * this method is responsible for getting the task data needed according to
	 * specific events to generate the report
	 * 
	 * @param typesList
	 * @param events
	 * @param tasks
	 * @param result
	 * @return
	 */
	public static boolean getTasksEventsReport(Set<TaskType> typesList,
			List<Event> events, List<Task> tasks, LinkedList<String> result) {
		int eventCounter = 0;
		String message = "";
		LinkedList<TaskType> tt = new LinkedList<TaskType>();
		LinkedList<Task> eventTasks = new LinkedList<Task>();
		List<Task> evTask = new LinkedList<Task>();

		for (int i = 0; i < events.size(); i++) {
			eventCounter = 0;
			evTask = events.get(i).getEventTasks();
			for (int k = 0; k < tasks.size(); k++) {
				for (int j = 0; j < evTask.size(); j++) {
					if (tasks.get(k) == evTask.get(j)) {
						eventTasks.add(evTask.get(j));
						evTask.remove(j);
						j--;
						eventCounter++;
					}
				}
			}
			message = "Total Tasks in event : " + events.get(i).name + " : "
					+ eventCounter;
			result.addLast(message);
			tt.addAll(typesList);
			int c = 0;
			for (int l = 0; l < eventTasks.size(); l++) {
				for (int m = 0; m < eventTasks.size(); m++) {
					if (tt.get(0) == eventTasks.get(m).type) {
						eventTasks.remove(m);
						l--;
						m--;
						c++;
					}
				}
				if (!tt.isEmpty() && !events.isEmpty()) {
					message = "Total tasks of type " + tt.get(0).type
							+ " in Event " + events.get(i).name + " : " + c;
					result.addLast(message);
					tt.remove(0);
				}
			}
		}
		return true;
	}

	/**
	 * this method is responsible for converting an array of taskTypes ids to
	 * linkedlist of ids
	 * 
	 * @param taskTypes
	 * @return
	 */
	public static LinkedList<Long> getTaskTypes(long[] taskTypes, long projectId) {
		Project project = Project.findById(projectId);
		LinkedList<Long> type = new LinkedList<Long>();

		for (int i = 0; i < taskTypes.length; i++) {
			if (taskTypes[i] != 0) {
				type.addLast(taskTypes[i]);
			} else {
				while (!type.isEmpty()) {
					type.removeFirst();
				}
				List<TaskType> taskTypess = TaskType.getAllTaskTypes();
				for (int k = 0; k < taskTypess.size(); k++) {
					type.addLast((Long) taskTypess.get(k).getEntityId());
				}
				if (!project.taskTypes.isEmpty()) {
					List<TaskType> projectTypes = project.taskTypes;
					for (int j = 0; j < projectTypes.size(); j++) {
						type.addLast((Long) projectTypes.get(j).getEntityId());
					}
				}
				break;
			}
		}

		return type;
	}

	/**
	 * this method is responsible for converting an array of taskStatus ids to a
	 * linkedlist of ids
	 * 
	 * @param taskStatus
	 * @return
	 */
	public static LinkedList<Long> getTaskStatus(long[] taskStatus,
			long projectId) {
		Project project = Project.findById(projectId);
		LinkedList<Long> status = new LinkedList<Long>();
		for (int i = 0; i < taskStatus.length; i++) {
			if (taskStatus[i] != 0) {
				status.addLast(taskStatus[i]);
			} else {
				while (!status.isEmpty()) {
					status.removeFirst();
				}
				List<TaskStatus> taskStatuses = TaskStatus.getAllTaskStatuses();
				for (int k = 0; k < taskStatuses.size(); k++) {
					status.addLast((Long) taskStatuses.get(k).getEntityId());
				}
				if (!project.taskStatuses.isEmpty()) {
					List<TaskStatus> projectStatus = project.taskStatuses;
					for (int j = 0; j < projectStatus.size(); j++) {
						status.addLast((Long) projectStatus.get(i)
								.getEntityId());
					}
				}
				break;
			}
		}
		return status;
	}

	/**
	 * this method is responsible for converting an array of components ids to
	 * linkedlist of ids
	 * 
	 * @param components
	 * @return
	 */
	public static LinkedList<Long> getComponentsIds(long[] components) {
		LinkedList<Long> comp = new LinkedList<Long>();
		for (int i = 0; i < components.length; i++) {
			if (components[i] != 0) {
				comp.addLast(components[i]);
			} else {
				while (!comp.isEmpty()) {
					comp.removeFirst();
				}
				break;
			}
		}
		return comp;
	}

}
